import json
import datetime
import os
import sys
import glob
import time
import tensorflow as tf
import concurrent.futures
os.environ["CUDA_VISIBLE_DEVICES"] = '0,6,7' 
# 添加项目根目录到Python路径
PROJECT_ROOT = "/opt/wyh/LSP_book_rec"
sys.path.insert(0, PROJECT_ROOT)

# 设置工作目录（可选）
os.chdir(PROJECT_ROOT)
sys.path.append("./")
current_path = os.getcwd()
print("当前路径是:", current_path)

from logs.log import setup_custom_logger
from Dataset.pull_data_from_sql_class import pullDataFromSql

class scheduledUpdater(object):

    def __init__(self):
        self.my_logger = self._setup_logger()
        self.start_time = "22:00"
        self.end_time = "07:00"
        self.max_retries = 1  # 最大重试次数
        self.config_dir = "/opt/wyh/LSP_book_rec/configs"
        db_dir = "/opt/wyh/LSP_book_rec/global_configs"
        self.db_config_path = os.path.join(db_dir, "mysql_db_config.json")
        # 获取所有物理 GPU 设备列表
        gpus = tf.config.experimental.list_physical_devices('GPU')
        self.max_workers = len(gpus)

    def _setup_logger(self):
        """
        设置日志记录器
        """
        log_dir = os.path.join(os.path.dirname(__file__), '..', 'Logfiles')
        file_name = str(datetime.datetime.now().strftime('%Y-%m-%d'))
        return setup_custom_logger(os.path.join(log_dir, f'{file_name}.log'), log_level="INFO")


    def is_in_time_window(self, start, end, now):
        """判断当前时间是否在指定时间窗口内"""
        start_time = datetime.datetime.strptime(start, "%H:%M").time()
        end_time = datetime.datetime.strptime(end, "%H:%M").time()
        now_time = now.time()
        
        # 处理跨天情况（例如 22:00 到次日 7:00）
        if start_time < end_time:
            return start_time <= now_time <= end_time
        else:
            return now_time >= start_time or now_time <= end_time

    def process_group(self, groupName):
        
        
        json_file = os.path.join(self.config_dir, f'{groupName}.json')
        
        print("json_file", json_file)
        for attempt in range(self.max_retries + 1):
            try:
                # 每次尝试重新初始化以生成新签名
                pullProc = pullDataFromSql(group_name=groupName, config_path=json_file, db_config_path=self.db_config_path)
                # base_url, headers, conn = initial_load(json_file)
                # print("hello")
                pullProc.update_local_database()
            except Exception as e:
                print(f"Error processing {groupName}: {e}")
                if attempt < self.max_retries:
                    self.my_logger.error(f"Retrying {groupName} after 1 second...")
                    time.sleep(1)  # 等待1s后重试
                else:
                    self.my_logger.error(f"Max retries ({self.max_retries}) exceeded for {groupName}")


    def pull_specify_data(self):
        """模拟数据拉取操作（替换为实际逻辑）"""
        # config_path = f"../configs/{institution_name}.json"
        # pdata = pullDataFromSql(config_path=config_path, group_name=institution_name)
        # pdata.update_local_database()

        groupNames = ['GZU']
        # groupNames = ['SHMTU', "LUIBE", "JXSTNU"]
        group_num = len(groupNames)
        # groupNames = ["ECNU"]  # 示例中只有一个机构
        if self.max_workers > group_num:
            self.max_workers = group_num
        # 根据机构数量选择执行方式
        if group_num == 1:
            # 单机构直接同步执行
            self.process_group(groupNames[0])
        else:
            # 由于 CUDA 上下文在多线程中容易出现不安全问题，更推荐使用多进程。每个进程独立加载模型和初始化 GPU，上下文不会共享，从而避免 segmentation fault。
            with concurrent.futures.ProcessPoolExecutor(max_workers=self.max_workers) as executor:
                executor.map(self.process_group, groupNames)


    def pull_all_data(self, institution_name):
        """模拟数据拉取操作（替换为实际逻辑）"""
        config_path = f"/opt/wyh/LSP_book_rec/configs/{institution_name}.json"
        pdata = pullDataFromSql(config_path=config_path, group_name=institution_name)
        pdata.update_local_database()
        print(f"拉取 {institution_name} 的数据...")

    def main(self):

        # 获取当前时间
        now = datetime.datetime.now()
        
        # 遍历 configs 目录下的所有 JSON 配置文件
        config_dir = "/opt/wyh/LSP_book_rec/configs/*.json"
        exclude_jsons = ["/opt/wyh/LSP_book_rec/configs/test.json", "/opt/wyh/LSP_book_rec/configs/default.json", "/opt/wyh/LSP_book_rec/configs/CAU.json"]
        for config_file in glob.glob(config_dir):
            if config_file not in exclude_jsons:

                print("config_file", config_file)

                with open(config_file, 'r', encoding='utf-8') as f:
                    config = json.load(f)
                
                # 获取机构名称（从文件名提取）
                institution_name = os.path.basename(config_file).split('.')[0]
                database_type = config.get("database", "other")  # 默认值 "other"
                print("institution", institution_name)
                print("database", database_type)
                # exit()
                # 根据 database 类型判断拉取逻辑
                if database_type == "aliyun":
                    if self.is_in_time_window(self.start_time, self.end_time, now):
                        self.pull_all_data(institution_name)
                    else:
                        self.my_logger(f"跳过 {institution_name}，当前时间不在 22:00-7:00 范围内。")
                else:
                    self.pull_all_data(institution_name)  # 全天可拉取
            else:
                continue


if __name__ == "__main__":
    sc = scheduledUpdater()
    sc.pull_specify_data()